/*
 * Cube.cpp
 *
 *  Created on: 28/03/2013
 *      Author: gonzalo
 */

#include "Cube.h"

#include <GL/freeglut.h>

GLfloat * Cube::static_vertex_buffer = NULL;
GLuint * Cube::static_index_buffer = NULL;
GLfloat * Cube::static_normal_buffer = NULL;
GLfloat * Cube::static_tangent_buffer = NULL;
GLfloat * Cube::static_texture_buffer = NULL;

GLuint Cube::static_vertex_buffer_size = 0;
GLuint Cube::static_index_buffer_size = 0;
GLuint Cube::static_normal_buffer_size = 0;

DatosVertice * Cube::static_vertices = NULL;
unsigned int * Cube::static_indices = NULL;
GLuint Cube::static_vertex_buffer_object = 0;
GLuint Cube::static_index_buffer_object = 0;

void Cube::create_vertex_buffer() {
	// Especifico los puntos del cubo
	set_coords3(static_vertex_buffer, 0, 0.5, 0.5, -0.5);
	set_coords3(static_vertex_buffer, 1, 0.5, -0.5, -0.5);
	set_coords3(static_vertex_buffer, 2, -0.5, -0.5, -0.5);
	set_coords3(static_vertex_buffer, 3, -0.5, 0.5, -0.5);

	set_coords3(static_vertex_buffer, 4, 0.5, 0.5, 0.5);
	set_coords3(static_vertex_buffer, 5, -0.5, 0.5, 0.5);
	set_coords3(static_vertex_buffer, 6, -0.5, -0.5, 0.5);
	set_coords3(static_vertex_buffer, 7, 0.5, -0.5, 0.5);

	set_coords3(static_vertex_buffer, 8, 0.5, -0.5, 0.5);
	set_coords3(static_vertex_buffer, 9, -0.5, -0.5, 0.5);
	set_coords3(static_vertex_buffer, 10, -0.5, -0.5, -0.5);
	set_coords3(static_vertex_buffer, 11, 0.5, -0.5, -0.5);

	set_coords3(static_vertex_buffer, 12, 0.5, 0.5, 0.5);
	set_coords3(static_vertex_buffer, 13, 0.5, 0.5, -0.5);
	set_coords3(static_vertex_buffer, 14, -0.5, 0.5, -0.5);
	set_coords3(static_vertex_buffer, 15, -0.5, 0.5, 0.5);

	set_coords3(static_vertex_buffer, 16, -0.5, 0.5, 0.5);
	set_coords3(static_vertex_buffer, 17, -0.5, 0.5, -0.5);
	set_coords3(static_vertex_buffer, 18, -0.5, -0.5, -0.5);
	set_coords3(static_vertex_buffer, 19, -0.5, -0.5, 0.5);

	set_coords3(static_vertex_buffer, 20, 0.5, 0.5, 0.5);
	set_coords3(static_vertex_buffer, 21, 0.5, -0.5, 0.5);
	set_coords3(static_vertex_buffer, 22, 0.5, -0.5, -0.5);
	set_coords3(static_vertex_buffer, 23, 0.5, 0.5, -0.5);

}

void Cube::create_normal_buffer() {
	// Especifico la normal que tiene cada punto
	set_coords3(static_normal_buffer, 0, 0.0, 0.0, -1.0);
	set_coords3(static_normal_buffer, 1, 0.0, 0.0, -1.0);
	set_coords3(static_normal_buffer, 2, 0.0, 0.0, -1.0);
	set_coords3(static_normal_buffer, 3, 0.0, 0.0, -1.0);

	set_coords3(static_normal_buffer, 4, 0.0, 0.0, 1.0);
	set_coords3(static_normal_buffer, 5, 0.0, 0.0, 1.0);
	set_coords3(static_normal_buffer, 6, 0.0, 0.0, 1.0);
	set_coords3(static_normal_buffer, 7, 0.0, 0.0, 1.0);

	set_coords3(static_normal_buffer, 8, 0.0, -1.0, 0.0);
	set_coords3(static_normal_buffer, 9, 0.0, -1.0, 0.0);
	set_coords3(static_normal_buffer, 10, 0.0, -1.0, 0.0);
	set_coords3(static_normal_buffer, 11, 0.0, -1.0, 0.0);

	set_coords3(static_normal_buffer, 12, 0.0, 1.0, 0.0);
	set_coords3(static_normal_buffer, 13, 0.0, 1.0, 0.0);
	set_coords3(static_normal_buffer, 14, 0.0, 1.0, 0.0);
	set_coords3(static_normal_buffer, 15, 0.0, 1.0, 0.0);

	set_coords3(static_normal_buffer, 16, -1.0, 0.0, 0.0);
	set_coords3(static_normal_buffer, 17, -1.0, 0.0, 0.0);
	set_coords3(static_normal_buffer, 18, -1.0, 0.0, 0.0);
	set_coords3(static_normal_buffer, 19, -1.0, 0.0, 0.0);

	set_coords3(static_normal_buffer, 20, 1.0, 0.0, 0.0);
	set_coords3(static_normal_buffer, 21, 1.0, 0.0, 0.0);
	set_coords3(static_normal_buffer, 22, 1.0, 0.0, 0.0);
	set_coords3(static_normal_buffer, 23, 1.0, 0.0, 0.0);

	set_coords3(static_tangent_buffer, 0, 1.0, 0.0, 0.0);
	set_coords3(static_tangent_buffer, 1, 1.0, 0.0, 0.0);
	set_coords3(static_tangent_buffer, 2, 1.0, 0.0, 0.0);
	set_coords3(static_tangent_buffer, 3, 1.0, 0.0, 0.0);

	set_coords3(static_tangent_buffer, 4, -1.0, 0.0, 0.0);
	set_coords3(static_tangent_buffer, 5, -1.0, 0.0, 0.0);
	set_coords3(static_tangent_buffer, 6, -1.0, 0.0, 0.0);
	set_coords3(static_tangent_buffer, 7, -1.0, 0.0, 0.0);

	set_coords3(static_tangent_buffer, 8, 0.0, 0.0, 1.0);
	set_coords3(static_tangent_buffer, 9, 0.0, 0.0, 1.0);
	set_coords3(static_tangent_buffer, 10, 0.0, 0.0, 1.0);
	set_coords3(static_tangent_buffer, 11, 0.0, 0.0, 1.0);

	set_coords3(static_tangent_buffer, 12, 0.0, 0.0, -1.0);
	set_coords3(static_tangent_buffer, 13, 0.0, 0.0, -1.0);
	set_coords3(static_tangent_buffer, 14, 0.0, 0.0, -1.0);
	set_coords3(static_tangent_buffer, 15, 0.0, 0.0, -1.0);

	set_coords3(static_tangent_buffer, 16, 0.0, 1.0, 0.0);
	set_coords3(static_tangent_buffer, 17, 0.0, 1.0, 0.0);
	set_coords3(static_tangent_buffer, 18, 0.0, 1.0, 0.0);
	set_coords3(static_tangent_buffer, 19, 0.0, 1.0, 0.0);

	set_coords3(static_tangent_buffer, 20, 0.0, -1.0, 0.0);
	set_coords3(static_tangent_buffer, 21, 0.0, -1.0, 0.0);
	set_coords3(static_tangent_buffer, 22, 0.0, -1.0, 0.0);
	set_coords3(static_tangent_buffer, 23, 0.0, -1.0, 0.0);

}

void Cube::create_index_buffer() {

	for (uint i = 0; i < static_vertex_buffer_size; i++) {
		static_index_buffer[i] = i;
	}

}

void Cube::create_texture_buffer() {

	////// Archivo Imagen de textura /////
	// (0,0)							//
	//	----------------------------	//
	//	|		 |		  | 	   |	//
	//	| Cara 1 | Cara 2 | Cara 3 |	//
	//	|		 |		  |		   |	//
	//	|---------------------------	//
	//	| 		 | 	 	  |        |	//
	//	| Cara 4 | Cara 5 | Cara 6 |	//
	//	| 		 |        |        |	//
	//  ----------------------------	//
	//                          (1,1)	//
	//////////////////////////////////////

	set_coords2(static_texture_buffer, 0, 0.0, 0.0);
	set_coords2(static_texture_buffer, 1, 1.0 / 3.0, 0.0);
	set_coords2(static_texture_buffer, 2, 1.0 / 3.0, 0.5);
	set_coords2(static_texture_buffer, 3, 0.0, 0.5);

	set_coords2(static_texture_buffer, 4, 1.0 / 3.0, 0.0);
	set_coords2(static_texture_buffer, 5, 2.0 / 3.0, 0.0);
	set_coords2(static_texture_buffer, 6, 2.0 / 3.0, 0.5);
	set_coords2(static_texture_buffer, 7, 1.0 / 3.0, 0.5);

	set_coords2(static_texture_buffer, 8, 2.0 / 3.0, 0.0);
	set_coords2(static_texture_buffer, 9, 1.0, 0.0);
	set_coords2(static_texture_buffer, 10, 1.0, 0.5);
	set_coords2(static_texture_buffer, 11, 2.0 / 3.0, 0.5);

	set_coords2(static_texture_buffer, 12, 0.0, 0.5);
	set_coords2(static_texture_buffer, 13, 1.0 / 3.0, 0.5);
	set_coords2(static_texture_buffer, 14, 1.0 / 3.0, 1.0);
	set_coords2(static_texture_buffer, 15, 0.0, 1.0);

	set_coords2(static_texture_buffer, 16, 1.0 / 3.0, 0.5);
	set_coords2(static_texture_buffer, 17, 2.0 / 3.0, 0.5);
	set_coords2(static_texture_buffer, 18, 2.0 / 3.0, 1.0);
	set_coords2(static_texture_buffer, 19, 1.0 / 3.0, 1.0);

	set_coords2(static_texture_buffer, 20, 2.0 / 3.0, 0.5);
	set_coords2(static_texture_buffer, 21, 1.0, 0.5);
	set_coords2(static_texture_buffer, 22, 1.0, 1.0);
	set_coords2(static_texture_buffer, 23, 2.0 / 3.0, 1.0);

}

void Cube::instantiate_buffer() {
	static_vertex_buffer_size = 3 * 8; 	// 24 elementos
	static_normal_buffer_size = 3 * 8; 	// 24 elementos
	static_index_buffer_size = 4 * 6;	// 24 elementos
	static_normal_buffer_size = 3 * 8 * 3;

	static_vertex_buffer = new GLfloat[3 * static_vertex_buffer_size];
	static_normal_buffer = new GLfloat[3 * static_normal_buffer_size];
	static_tangent_buffer = new GLfloat[3 * static_normal_buffer_size];
	static_index_buffer = new GLuint[static_index_buffer_size];
	static_texture_buffer = new GLfloat[2 * static_normal_buffer_size];

	create_vertex_buffer();
	create_index_buffer();
	create_normal_buffer();
	create_texture_buffer();
}

void Cube::create_mesh_cube() {
	DatosVertice datos;
	size = 24;
	vertices = new DatosVertice[size];
	index_size = size;
	indices = new unsigned int[index_size];

	// Cara1
	datos.position = glm::vec3(0.5, -0.5, -0.5);
	datos.normal = glm::vec3(1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[0] = datos;
	datos.position = glm::vec3(0.5, -0.5, 0.5);
	datos.normal = glm::vec3(1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[1] = datos;
	datos.position = glm::vec3(0.5, 0.5, 0.5);
	datos.normal = glm::vec3(1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[2] = datos;
	datos.position = glm::vec3(0.5, 0.5, -0.5);
	datos.normal = glm::vec3(1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[3] = datos;

	// Cara 2
	datos.position = glm::vec3(-0.5, -0.5, -0.5);
	datos.normal = glm::vec3(-1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[4] = datos;
	datos.position = glm::vec3(-0.5, 0.5, -0.5);
	datos.normal = glm::vec3(-1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[5] = datos;
	datos.position = glm::vec3(-0.5, 0.5, 0.5);
	datos.normal = glm::vec3(-1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[6] = datos;
	datos.position = glm::vec3(-0.5, -0.5, 0.5);
	datos.normal = glm::vec3(-1.0, 0.0, 0.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[7] = datos;

	// Cara 3
	datos.position = glm::vec3(-0.5, -0.5, -0.5);
	datos.normal = glm::vec3(0.0, -1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[8] = datos;
	datos.position = glm::vec3(-0.5, -0.5, 0.5);
	datos.normal = glm::vec3(0.0, -1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[9] = datos;
	datos.position = glm::vec3(0.5, -0.5, 0.5);
	datos.normal = glm::vec3(0.0, -1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[10] = datos;
	datos.position = glm::vec3(0.5, -0.5, -0.5);
	datos.normal = glm::vec3(0.0, -1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[11] = datos;

	// Cara 4
	datos.position = glm::vec3(-0.5, 0.5, -0.5);
	datos.normal = glm::vec3(0.0, 1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[12] = datos;
	datos.position = glm::vec3(0.5, 0.5, -0.5);
	datos.normal = glm::vec3(0.0, 1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[13] = datos;
	datos.position = glm::vec3(0.5, 0.5, 0.5);
	datos.normal = glm::vec3(0.0, 1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[14] = datos;
	datos.position = glm::vec3(-0.5, 0.5, 0.5);
	datos.normal = glm::vec3(0.0, 1.0, 0.0);
	datos.tangent = glm::vec3(0.0, 0.0, 1.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[15] = datos;

	// Cara 5
	datos.position = glm::vec3(-0.5, -0.5, -0.5);
	datos.normal = glm::vec3(0.0, 0.0, -1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[16] = datos;
	datos.position = glm::vec3(0.5, -0.5, -0.5);
	datos.normal = glm::vec3(0.0, 0.0, -1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[17] = datos;
	datos.position = glm::vec3(0.5, 0.5, -0.5);
	datos.normal = glm::vec3(0.0, 0.0, -1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[18] = datos;
	datos.position = glm::vec3(-0.5, 0.5, -0.5);
	datos.normal = glm::vec3(0.0, 0.0, -1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[19] = datos;

	// Cara 6
	datos.position = glm::vec3(-0.5, -0.5, 0.5);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[20] = datos;
	datos.position = glm::vec3(-0.5, 0.5, 0.5);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[21] = datos;
	datos.position = glm::vec3(0.5, 0.5, 0.5);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[22] = datos;
	datos.position = glm::vec3(0.5, -0.5, 0.5);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(1.0, 0.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[23] = datos;

	for (uint i = 0; i < 24; i++) {
		indices[i] = i;
	}
}

Cube::Cube(GLuint program) :
		Figure(program) {

	/*if (static_vertex_buffer == NULL) {
	 instantiate_buffer();
	 }

	 this->vertex_buffer = static_vertex_buffer;
	 this->index_buffer = static_index_buffer;
	 this->normal_buffer = static_normal_buffer;

	 this->vertex_buffer_size = static_vertex_buffer_size;
	 this->index_buffer_size = static_index_buffer_size;
	 this->normal_buffer_size = static_normal_buffer_size;
	 this->texture_buffer = static_texture_buffer;
	 this->tangent_buffer = static_tangent_buffer;*/

	//if (static_vertices == NULL) {
	glGenBuffers(1, &vertex_buffer_object);
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
	glGenBuffers(1, &index_buffer_object);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object);

	this->create_mesh_cube();

	glBufferData(GL_ARRAY_BUFFER, size * sizeof(DatosVertice), vertices, GL_STATIC_DRAW);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size * sizeof(unsigned int), indices, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	//this->type = GL_TRIANGLES;
	this->type = GL_QUADS;
	//}

	delete[] vertices;
	delete[] indices;

	this->vertices = NULL;
	this->indices = NULL;

}

Cube::~Cube() {
	/*if (static_vertex_buffer != NULL) {
	 static_vertex_buffer = NULL;
	 delete[] vertex_buffer;
	 delete[] normal_buffer;
	 delete[] index_buffer;
	 delete[] texture_buffer;
	 }*/
	//delete [] indices;
	//delete [] vertices;
	glDeleteBuffers(1, &vertex_buffer_object);
	glDeleteBuffers(1, &index_buffer_object);

}

void Cube::draw(GLuint program, glm::mat4 & world_matrix) {
	glm::mat4 matriz = world_matrix * this->model_matrix;

	GLint location;

	bind_model_matrix(program,matriz);
	calculate_and_bind_normal_matrix(program,matriz);

	/*glEnableClientState(GL_VERTEX_ARRAY);
	 glEnableClientState(GL_NORMAL_ARRAY);
	 glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	 bind_tangent_buffer("tangent");

	 glVertexPointer(3, GL_FLOAT, 0, vertex_buffer);
	 glNormalPointer(GL_FLOAT, 0, normal_buffer);
	 glTexCoordPointer(2, GL_FLOAT, 0, texture_buffer);

	 glDrawElements(GL_QUADS, index_buffer_size, GL_UNSIGNED_INT, index_buffer);

	 if (this->show_normals) {
	 draw_normals();
	 }

	 glDisableClientState(GL_VERTEX_ARRAY);
	 glDisableClientState(GL_NORMAL_ARRAY);
	 glDisableClientState(GL_TEXTURE_COORD_ARRAY);*/

	int vertex = glGetAttribLocation(program, "vertex"); //0
	int normal = glGetAttribLocation(program, "normal"); //1
	int tangent = glGetAttribLocation(program, "tangent"); //2
	int color = glGetAttribLocation(program, "color"); //3
	int UV = glGetAttribLocation(program, "UV"); //4

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object);

	/*
	 std::string str = "texture";
	 for (int i = 0; i < textures.size(); i++) {
	 glActiveTexture(GL_TEXTURE0 + i);
	 glBindTexture(GL_TEXTURE_2D, textures[i].id);
	 glUniform1i(glGetUniformLocation(programId, (str + (char) (i + '0')).c_str()), i);
	 }*/

	glEnableVertexAttribArray(vertex);
	glVertexAttribPointer(vertex, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), 0);

	glEnableVertexAttribArray(normal);
	glVertexAttribPointer(normal, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (3 * sizeof(float)));

	glEnableVertexAttribArray(tangent);
	glVertexAttribPointer(tangent, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (6 * sizeof(float)));

	glEnableVertexAttribArray(color);
	glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (9 * sizeof(float)));

	glEnableVertexAttribArray(UV);
	glVertexAttribPointer(UV, 2, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (12 * sizeof(float)));

	// TEXTURE2D
	if (with_texture) {

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, this->texture);
		location = glGetUniformLocation(program, "Texture");
		if (location >= 0) {
			glUniform1i(location, 0);
		}
		location = glGetUniformLocation(program, "with_texture");
		if (location >= 0) {
			glUniform1i(location, 1);
		}
	} else {
		location = glGetUniformLocation(program, "with_texture");
		if (location >= 0) {
			glUniform1i(location, 0);
		}
	}

	glDrawElements(this->type, index_size, GL_UNSIGNED_INT, 0);

	glDisableVertexAttribArray(vertex);
	glDisableVertexAttribArray(normal);
	glDisableVertexAttribArray(tangent);
	glDisableVertexAttribArray(color);
	glDisableVertexAttribArray(UV);

	if (with_texture) {
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void Cube::set_color(const glm::vec3 & color) {
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);

	this->vertices = (DatosVertice *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

	for (uint i = 0; i < size; i++) {
		this->vertices[i].color = color;
	}


	glUnmapBuffer(GL_ARRAY_BUFFER);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Cube::change_texture_data(const std::vector<DatosVertice> & datos_texturas) {
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);

	this->vertices = (DatosVertice *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

	for (uint i = 0; i < datos_texturas.size(); i++) {
		this->vertices[i].texture = datos_texturas[i].texture;
	}

	glUnmapBuffer(GL_ARRAY_BUFFER);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
}
